package com.linzm.leetcode.primary.数组.螺旋矩阵II;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Author zimingl
 * @Date 2022/10/6 19:07
 * @Description: TODO
 */
public class 数组29顺时针打印矩阵 {

    /**
     * 对于每层，从左上方开始以顺时针的顺序遍历所有元素。假设当前层的左上角位于 (\textit{top}, \textit{left})(top,left)，右下角位于 (\textit{bottom}, \textit{right})(bottom,right)，按照如下顺序遍历当前层的元素。
     * 从左到右遍历上侧元素，依次为 (\textit{top}, \textit{left})(top,left) 到 (\textit{top}, \textit{right})(top,right)。
     * 从上到下遍历右侧元素，依次为 (\textit{top} + 1, \textit{right})(top+1,right) 到 (\textit{bottom}, \textit{right})(bottom,right)。
     * 如果 \textit{left} < \textit{right}left<right 且 \textit{top} < \textit{bottom}top<bottom，则从右到左遍历下侧元素，依次为 (\textit{bottom}, \textit{right} - 1)(bottom,right−1) 到 (\textit{bottom}, \textit{left} + 1)(bottom,left+1)，以及从下到上遍历左侧元素，依次为 (\textit{bottom}, \textit{left})(bottom,left) 到 (\textit{top} + 1, \textit{left})(top+1,left)。
     * 遍历完当前层的元素之后，将 \textit{left}left 和 \textit{top}top 分别增加 11，将 \textit{right}right 和 \textit{bottom}bottom 分别减少 11，进入下一层继续遍历，直到遍历完所有元素为止
     *
     * @param matrix
     * @return
     */

    public int[] spiralOrder(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return new int[0];
        }
        int rows = matrix.length, columns = matrix[0].length;
        int[] order = new int[rows * columns];
        int index = 0;
        int left = 0, right = columns - 1, top = 0, bottom = rows - 1;
        while (left <= right && top <= bottom) {
            for (int column = left; column <= right; column++) {
                order[index++] = matrix[top][column];
            }
            for (int row = top + 1; row <= bottom; row++) {
                order[index++] = matrix[row][right];
            }
            if (left < right && top < bottom) {
                for (int column = right - 1; column > left; column--) {
                    order[index++] = matrix[bottom][column];
                }
                for (int row = bottom; row > top; row--) {
                    order[index++] = matrix[row][left];
                }
            }
            left++;
            right--;
            top++;
            bottom--;
        }
        return order;
    }

    @Test
    public void test() {
        int[][] matrix = new int[][]{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
        int[] ints = spiralOrder(matrix);
        int[] ints2 = spiralOrder2(matrix);
        String[] s1 = Arrays.stream(ints).mapToObj(String::valueOf).toArray(String[]::new);
        System.out.println(String.join("", s1));
        String[] s2 = Arrays.stream(ints2).mapToObj(String::valueOf).toArray(String[]::new);
        System.out.println(String.join("", s2));
    }

    public int[] spiralOrder2(int[][] matrix) {
        if (matrix == null || matrix.length == 0) {
            return new int[0];
        }
        List<Integer> list = new ArrayList<>();
        int top = 0, bottom = matrix.length - 1, left = 0, right = matrix[0].length - 1;
        while (top < bottom && left < right) {
            // 上层
            for (int i = left; i < right; i++) {
                list.add(matrix[top][i]);
            }
            // 右层
            for (int i = top; i < bottom; i++) {
                list.add(matrix[i][right]);
            }
            // 下层
            for (int i = right; i > left; i--) {
                list.add(matrix[bottom][i]);
            }
            // 左层
            for (int i = bottom; i > top; i--) {
                list.add(matrix[i][left]);
            }
            top++;
            bottom--;
            left++;
            right--;
        }
        // 剩下一列
        while (left == right && top <= bottom) {
            list.add(matrix[top][left]);
            top++;
        }
        // 剩下一行
        while (top == bottom && left <= right) {
            list.add(matrix[top][left]);
            left++;
        }
        return list.stream().mapToInt(x -> x).toArray();
    }

}
